#include "image.h"
#include "channel.h"

/* macro */
#define NUM_PAR_INPUT 4

#define PAR_W 1
#define PAR_H 2
#define PAR_S 3

/**
 * Receives and sends a stream of Gaussian images of dimensione width x heigth to an interpolator through a virtual channel.
 */

int main (int argc, char* argv []) {
    
    /* parameters to be inizialized (definitions) */
    int width, heigth, stream;
    int i, dim, device;
    unsigned char *image;
    float* gaussian_parameters;
    
    float memory_required;
    Channel* ch;
    
#ifdef PERFORMANCE
    struct timeval time_1, time_2;
    long int completion_time;
    double seconds, service_time;
#endif
    
#ifdef DEBUG
#define PATH_OPERAZIONI "./Debug/Gaussian_"
#define DIM 30
    char path [DIM];
    char numim [DIM];
#endif
    
    /* input check */
    if (argc != NUM_PAR_INPUT) {
        printf ("Number of parameters is wrong: program aborted\n");
        return -1;
    }
    
    /* initialization */
    width = atoi (argv [PAR_W]);
    heigth = atoi (argv [PAR_H]);
    stream = atoi (argv [PAR_S]);
    
    if (width <= 0 || heigth <= 0 || stream <= 0 || (width != heigth)) {
        printf ("One or more parameters are wrong: program aborted\n");
        return -1;
    }
    
    dim = width * heigth;
    image = NULL;
    i = 0;

    /* check on physical device */
    memory_required = (float)(width * heigth) * ( 2 * sizeof(unsigned char) + 9 * sizeof(float)) / MEGA;
    if ( (device = getPhysicalDevice (memory_required)) < 0) {
        printf ("Problem on physical device: program aborted\n");
        return -1;
    }
    
    /* creation virtual channel */
    if ((ch = createVirtualChannel (device, width, heigth)) == NULL) {
        printf ("Problem on allocating virtual channel: program aborted\n");
        return -1;
    }
        
    /* a local image is created and used EVERY time in the iterations for minimal inter-arrival time, in the real case there is a socket */
    image = createImage (width, heigth);
    
    /* start the loop on images */
    for (i = 0; i < stream; ++i) {
        
        if (i == 0) {
            
            /* performing the initialization for starting the interpolation */
            if ((gaussian_parameters = createParameters (image, width, heigth)) == NULL) {
                printf ("Problem on estimating the parameters of the Gaussian image: program aborted\n");
                return -1;
            }

#ifdef DEBUG
            /* print data */
            printf ("Parameters during the initialization:");
            printf ("\nAmpiezza massima: %f\n", gaussian_parameters [PAR_A]);
            printf ("Centro x: %f\n", gaussian_parameters [PAR_X]);
            printf ("Centro y: %f\n", gaussian_parameters [PAR_Y]);
            printf ("Varianza x: %f\n", gaussian_parameters [PAR_SX]);
            printf ("Varianza y: %f\n\n", gaussian_parameters [PAR_SY]);
#endif
            
            /* sending the parameters into the virtual channel */
            if (initializeVirtualChannel (ch, gaussian_parameters) != 0) {
                printf ("Problem on initializing the parameters of the channel: program aborted\n");
                return -1;
            }    
            
#ifdef PERFORMANCE
            /* initialization performance values */
            completion_time = 0;
            seconds = 0.0;
            service_time = 0.0;
            printf ("Stream of %d images %dx%d\n", stream, width, heigth);
            printf ("\n\nExecuting computation ... \n\n");
            /* take the time at the first iteration */
            gettimeofday (&time_1, NULL);
#endif

        }

#ifdef DEBUG
        /* create the path */
        strcpy (path, PATH_OPERAZIONI);
		sprintf(numim, "%d", i);
		strcat (path, numim);
		strcat (path, ".tiff");
        
        /* write the image */
        writeImage (image, path, width, heigth);
#endif
        
        /* --------  -------- WORK on images --------  -------- */

#ifdef DEBUG
        printf ("Work on image %d: ", i);
#endif
        
#ifdef PERFORMANCE
        submit (ch, image);
#else
        if (submit (ch, image) != 0) {
            printf ("Problem during the image %i\n", i);
            return -1;
        }  
#endif
        
        /* --------  -------- END WORK on images --------  -------- */
                
    }
    
#ifdef PERFORMANCE
    /* take the time and compute the difference */
    gettimeofday (&time_2, NULL);
    completion_time = getCompletionTime (&time_1, &time_2);
    seconds = (double) completion_time / (double) MICROSECONDSPERSECOND;
    service_time = seconds / (double) stream;
    printf ("\nCompletion time: %ld microseconds...that are roughly %f seconds\n", completion_time, seconds);
    printf ("Service time: %f seconds\n\n", service_time);
#endif
    
    /* take the result */
    if (getResult (ch, gaussian_parameters) != 0) {
        printf ("Problem on retriving results: program aborted");
        return -1;
    }

    /* print data */
    printf ("Final result:");
    printf ("\nAmpiezza massima: %f\n", gaussian_parameters [PAR_A]);
    printf ("Centro x: %f\n", gaussian_parameters [PAR_X]);
    printf ("Centro y: %f\n", gaussian_parameters [PAR_Y]);
    printf ("Varianza x: %f\n", gaussian_parameters [PAR_SX]);
    printf ("Varianza y: %f\n\n", gaussian_parameters [PAR_SY]);
    
    /* at the end we deallocate */
    destroyParameters (gaussian_parameters);
    destroyImage (image);
    destroyVirtualChannel (ch);
    
    return 0;
}